package com.comunity_cloud.client.model.communication;

import java.io.IOException;
import java.util.Hashtable;
import java.util.Map;

import net.rudp.ReliableSocket;
import net.rudp.SinglePortReliableSocket;

import com.comunity_cloud.client.model.MainModel2;
import com.user_hosted_storage.dto.ClientDTO;

public class ConnectionsManager {

	private Map<Long, PeerConnection> peerConnections = new Hashtable<>();
	
	private Map<Long,Object> clientSemaphores = new Hashtable<>();
	
	private static ConnectionsManager instance = new ConnectionsManager();
	
	private ConnectionsManager() {
		
	}
	
	public static ConnectionsManager getInstance() {
		return instance;
	}
	
	public void addConnction(PeerConnection peerConnection) {
		peerConnections.put(peerConnection.getClientId(),peerConnection);
		synchronized (clientSemaphores) {
			Object semaphore = clientSemaphores.get(peerConnection.getClientId());
			if(semaphore != null) {
				synchronized (semaphore) {
					semaphore.notifyAll();
				}
			}
		}
	}
	
	public PeerConnection getPeerConnection(long clientId) throws IOException{
		PeerConnection peerConnection = peerConnections.get(clientId);
		if(peerConnection == null) {
			if(MainModel2.getInstance().getClientDTO().getId() > clientId) {
				ClientDTO client = MainModel2.getInstance().getClient(clientId);
				
				ReliableSocket socket = new SinglePortReliableSocket(client.getIp(), client.getAcceptPort());
				peerConnection = new PeerConnection(socket, clientId);
				peerConnections.put(clientId, peerConnection);
				peerConnection.start();
			} else {
				Object semaphore;
				synchronized (clientSemaphores) {
					semaphore = clientSemaphores.get(clientId);
					if(semaphore == null) {
						semaphore = new Object();
						clientSemaphores.put(clientId, semaphore);
					}
				}
				
				synchronized (semaphore) {
					try {
						semaphore.wait();
					} catch (InterruptedException e) {}
				}
				peerConnection = peerConnections.get(clientId);				
			}
		}
		
		return peerConnection;
	}

	public boolean connectionExists(long id) {
		return peerConnections.containsKey(id);
	}
	
}
